from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout
from PyQt5.QtCore import Qt, QObject, pyqtSignal
from typing import Optional, Dict, Any
import threading

from meet_record.meeting_record_viewer import MeetingRecordViewer
from voice_assistant.submodule_base import SubmoduleBase
from voice_assistant.event_system import EventNames
from voice_assistant.my_state import app_state  # 导入全局状态对象
from voice_assistant.my_config import MEET_STYLE

import logging
logger = logging.getLogger("MeetingRecordApp")
TIME_EXPIRE = 10  # 倒计时结束时间（秒）

# 窗口创建器类，用于跨线程创建窗口
class WindowCreator(QObject):
    # 定义信号，用于在主线程中创建窗口
    create_window_signal = pyqtSignal(object)
    window_created_signal = pyqtSignal()  # 窗口创建完成的信号
    
    def __init__(self):
        super().__init__()
        # 初始化窗口引用
        self._created_window = None
        self.record_view = None
        # 创建同步事件
        self._window_created_event = threading.Event()
        # 将信号连接到在主线程中执行的槽函数
        self.create_window_signal.connect(self._create_window_in_main_thread)
        
    def create_window(self, close_event_handler):
        """创建窗口并等待完成"""
        # 重置事件
        self._window_created_event.clear()
        # 发送信号
        self.create_window_signal.emit(close_event_handler)
        # 等待窗口创建完成
        self._window_created_event.wait(timeout=5.0)  # 添加超时防止永久阻塞
        return self._created_window, self.record_view
        
    def _create_window_in_main_thread(self, close_event_handler):
        """在主线程中创建窗口的槽函数"""
        logger.info("通过Signal在主线程中创建会议记录窗口...")
        try:
            self._created_window, self.record_view = create_meeting_window(close_event_handler)
        except Exception as e:
            logger.error(f"在主线程中创建窗口失败: {str(e)}")
            self._created_window = None
            self.record_view = None
        finally:
            # 设置事件，通知等待线程
            self._window_created_event.set()

# 创建会议窗口的函数，可以被外部调用
def create_meeting_window(closeEvent):
    """创建并返回会议记录窗口
    
    此函数可以被外部模块调用，用于创建会议记录窗口
    必须在主线程中调用
    """
    import threading
    if threading.current_thread() is not threading.main_thread():
        import logging
        logging.getLogger("MeetRecord").error("create_meeting_window 必须在主线程中调用")
        raise RuntimeError("create_meeting_window 必须在主线程中调用")
    
    # 获取当前应用实例
    app = QApplication.instance()
    if app is None:
        # 如果没有应用实例，创建一个新的
        import sys
        app = QApplication(sys.argv)
        
    # 创建主窗口
    main_window = QWidget()
    main_window.setWindowTitle("会议记录")
    main_window.resize(800, 600)
    main_window.setWindowFlags(Qt.Window)  # 确保窗口独立显示
    
    # 设置窗口图标，用于任务栏缩略图显示
    from PyQt5.QtGui import QIcon
     # 如果找不到指定图标，尝试使用应用默认图标
    app_icon = QApplication.instance().windowIcon()
    if not app_icon.isNull():
        main_window.setWindowIcon(app_icon)
       
    # 只将样式应用于会议窗口，而不是整个应用
    main_window.setStyleSheet(MEET_STYLE)
    
    # 将自定义的closeEvent方法绑定到窗口实例
    main_window.closeEvent = closeEvent
    
    # 添加会议记录查看器
    layout = QVBoxLayout(main_window)
    recordView = MeetingRecordViewer()
    layout.addWidget(recordView)
    
    # 显示窗口
    main_window.show()
    main_window.raise_()  # 确保窗口在最前面
    main_window.activateWindow()  # 激活窗口
    
    return main_window, recordView

# 供外部操作类
class MeetingRecordApp(SubmoduleBase):
    """会议记录模块的外部操作类"""
    
    def __init__(self):
        super().__init__("meet_record", "会议记录模块")
        self.app = None
        self.main_window = None
        self.record_view = None
        # 创建窗口创建器实例
        self.window_creator = WindowCreator()
        # 倒计时器相关属性
        self._timer = None
        self._timer_expired = False
        self.is_first_line = True
        
        # 订阅 UI_COMMAND 事件
        from voice_assistant.event_system import event_system, Events
        event_system.subscribe(Events.MEETING_RECORD, self.handle_ui_command)
    
    def start(self) -> bool:
        """启动会议记录模块"""

        if self.is_running:
            app_state.meeting_recording = True
            app_state.waiting_for_wake = False  # 保持唤醒状态
            
            # 如果最小化了，还原窗口大小
            if self.main_window.isMinimized():
                self.main_window.showNormal()
            return True
        
        # 确保在主线程中创建窗口
        result = self._start_in_main_thread()
        if result:
            # 创建倒计时器
            self.is_first_line = True
            self._timer_expired = False
            self._timer = threading.Timer(TIME_EXPIRE, self._on_timer_expired)
            self._timer.start()
        return result
    
    def _start_in_main_thread(self) -> bool:
        """使用Signal在主线程中执行启动逻辑"""
        
        try:
            # 检查当前线程
            current_thread = threading.current_thread()
            main_thread = threading.main_thread()
            
            if current_thread is main_thread:
                # 如果已经在主线程中，直接创建窗口
                logger.info("当前已在主线程中，直接创建会议记录窗口...")
                self.main_window, self.record_view = create_meeting_window(closeEvent=self.closeEvent)
            else:
                # 如果在非主线程中，使用Signal触发主线程创建窗口
                logger.info(f"当前在非主线程({current_thread.name})中，使用Signal在主线程中创建窗口...")
                # 使用同步方法等待窗口创建完成
                self.main_window, self.record_view = self.window_creator.create_window(self.closeEvent)
            
            self.record_view.startRecord()
            logger.info("会议记录视图已启动录制")
            self.record_view.add_record("开始录音", new_line=True)
            
            # 修改状态
            app_state.meeting_recording = True
            app_state.waiting_for_wake = False  # 保持唤醒状态
            self.is_running = True
            logger.info("会议记录窗口已成功创建并显示")
            return True
        except Exception as e:
            logger.error(f"创建会议窗口失败: {str(e)}")
            import traceback
            logger.error(traceback.format_exc())
            return False
        
    def closeEvent(self, event):
        logger.info("处理窗口关闭事件...")
        # 在窗口关闭时执行清理操作
        self.stop()  # 调用 stop 方法来清理和关闭记录
        
        # 清理样式表，避免影响其他窗口
        app = QApplication.instance()
        if app and hasattr(self.main_window, 'styleSheet') and self.main_window.styleSheet():
            # 只清理当前窗口的样式，不影响全局
            self.main_window.setStyleSheet("")
            
        event.accept()  # 允许窗口关闭
    
    def stop(self) -> bool:
        """停止会议记录模块"""
        app_state.meeting_recording = False
        self.is_first_line = False
        if not self.is_running:
            return True
            
        if self.main_window:
            # 关闭窗口前执行清理操作
            if self.record_view:
                # 如果需要，可以在这里添加记录视图的清理代码
                pass
                
            # 清理样式表，避免影响其他窗口
            self.main_window.setStyleSheet("")
            self.main_window.close()
            # 重置窗口和视图引用
            self.main_window = None
            self.record_view = None
            
        # 注销倒计时器
        if self._timer:
            self._timer.cancel()
            self._timer = None
        self.is_running = False
        return True
    
    def execute_command(self, command: str, params: Optional[Dict[str, Any]] = None) -> bool:
        if not self.is_running:
            return False
        
        if not self.main_window:
            return False
        
        # 重置倒计时器
        if(command == EventNames.RECORD_ADD):
            if self._timer:
                self._timer.cancel()
                self._timer = threading.Timer(TIME_EXPIRE, self._on_timer_expired)
                self._timer.start()
            
            text = params.get("text", "")
            new_line = True if self.is_first_line else self._timer_expired
            self.record_view.add_record(text, new_line=new_line)
            self._timer_expired = False
            self.is_first_line = False
            return True
        elif(command == EventNames.RECORD_START or command == EventNames.RECORD_STOP):
            # 停止|继续记录
            self.record_view.toggle_recording()
            return True
        elif(command == EventNames.RECORD_SUM):
            self.record_view.summarize_text()
            return True
        return False
    
    def minimize(self) -> bool:
        """最小化会议记录窗口"""
        if not self.is_running or not self.main_window:
            return False
        self.main_window.showMinimized()
        return True
        
    def _on_timer_expired(self):
        """倒计时器到期时的回调函数"""
        self._timer_expired = True
        
    def handle_ui_command(self, data: Dict[str, Any]) -> None:
        """处理 UI_COMMAND 事件
        
        Args:
            data: 事件数据，包含 command 和 params 字段
        """
        command = data.get("command")
        params = data.get("params", {})
        # logger.info(f"处理命令: {command}，{params}")
        
        # 将命令发送给子进程处理
        if command == EventNames.RECORD_EXIT:
            self.stop()
        elif command == EventNames.RECORD_CREATED:
            self.start()
        else: 
            self.execute_command(command=command, params=params)
